package com.ddone.finance.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.ddone.base.util.JwtUtils;
import com.ddone.common.exception.Assert;
import com.ddone.common.result.ResponseEnum;
import com.ddone.common.util.MD5Utils;
import com.ddone.common.util.RegexValidateUtils;
import com.ddone.finance.mapper.UserAccountMapper;
import com.ddone.finance.mapper.UserLoginRecordMapper;
import com.ddone.finance.pojo.entity.UserAccount;
import com.ddone.finance.pojo.entity.UserInfo;
import com.ddone.finance.mapper.UserInfoMapper;
import com.ddone.finance.pojo.entity.UserLoginRecord;
import com.ddone.finance.pojo.vo.*;
import com.ddone.finance.service.UserInfoService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ddone.finance.service.UserLoginRecordService;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import sun.security.util.Password;

import javax.annotation.Resource;
import java.util.UUID;

/**
 * <p>
 * 用户基本信息 服务实现类
 * </p>
 *
 * @author ddone
 * @since 2024-04-10
 */
@Service
public class UserInfoServiceImpl extends ServiceImpl<UserInfoMapper, UserInfo> implements UserInfoService {

    @Resource
    private UserAccountMapper userAccountMapper;

    @Resource
    private UserLoginRecordService userLoginRecordService;


    @Resource
    private UserInfoMapper userInfoMapper;

    @Transactional
    @Override
    public void register(RegisterVO registerVO) {
        // 判断用户是否已注册
        Integer count = baseMapper.selectCount(Wrappers.lambdaQuery(UserInfo.class).eq(UserInfo::getMobile, registerVO.getMobile()));
        // 如果存在,则抛异常
        Assert.isTrue(count == 0, ResponseEnum.MOBILE_EXIST_ERROR);

        // MD5 加盐 加密 防止暴力破解: 每个用户注册时生成一个salt
        // 铭文密码+盐加密

        String salt = UUID.randomUUID().toString().substring(0, 8);

        String password = MD5Utils.encrypt(MD5Utils.encrypt(registerVO.getPassword()) + salt);

        // 插入用户基本信息
        UserInfo userInfo = UserInfo
                .builder()
                .userType(registerVO.getUserType())
                .mobile(registerVO.getMobile())
                .name(registerVO.getMobile())
                .password(password)
                .status(UserInfo.STATUS_NORMAL)
                .salt(salt)
                .headImg("https://finance-loan.oss-cn-shanghai.aliyuncs.com/avatar/2024/04/16/821636263c8d493c9abbd8b775640755.jpeg")
                .integral(0)
                .build();

        baseMapper.insert(userInfo);

        // 创建会员账户
        UserAccount userAccount = new UserAccount();
        userAccount.setUserId(userInfo.getId());
        userAccountMapper.insert(userAccount);
    }

    @Override
    public String login(LoginVo loginVo, String ip) {
        String mobile = loginVo.getMobile();
        Assert.isTrue(RegexValidateUtils.checkCellphone(mobile), ResponseEnum.MOBILE_ERROR);
        Integer userType = loginVo.getUserType();
        UserInfo userInfo = baseMapper.selectOne(Wrappers.lambdaQuery(UserInfo.class)
                .eq(UserInfo::getMobile, mobile)
                .eq(UserInfo::getUserType, userType));
        Assert.notNull(userInfo, ResponseEnum.LOGIN_MOBILE_ERROR);
        Assert.equals(userInfo.getStatus(), UserInfo.STATUS_NORMAL, ResponseEnum.LOGIN_LOKED_ERROR);
        String password = MD5Utils.encrypt(MD5Utils.encrypt(loginVo.getPassword()) + userInfo.getSalt());
        Assert.equals(password, userInfo.getPassword(), ResponseEnum.LOGIN_PASSWORD_ERROR);
        // 记录登录日志
        userLoginRecordService.saveLoginLog(userInfo, ip);
        // 生成Token
        return JwtUtils.createToken(userInfo.getId(), userInfo.getName());
    }

    @Override
    public UserInfo getByOpenId(String openId) {
        return baseMapper.selectOne(Wrappers.lambdaQuery(UserInfo.class).eq(UserInfo::getOpenid, openId));
    }

    @Override
    public Page<UserInfo> pageWithCondition(Page<UserInfo> pageParam,
                                            UserInfoSearchVo userInfoSearchVo) {

        if (userInfoSearchVo == null) {
            return baseMapper.selectPage(pageParam, null);
        }

        String mobile = userInfoSearchVo.getMobile();
        Integer userType = userInfoSearchVo.getUserType();
        Integer status = userInfoSearchVo.getStatus();

        LambdaQueryWrapper<UserInfo> wrapper = Wrappers.lambdaQuery(UserInfo.class);
        wrapper.like(StringUtils.isNotBlank(mobile), UserInfo::getMobile, mobile)
                .eq(userType != null, UserInfo::getUserType, userType)
                .eq(status != null, UserInfo::getStatus, status);
        return this.page(pageParam, wrapper);
    }

    @Override
    public boolean checkMobile(String mobile) {

        LambdaQueryWrapper<UserInfo> wrapper = Wrappers.lambdaQuery(UserInfo.class);
        wrapper.eq(UserInfo::getMobile, mobile);
        Integer count = baseMapper.selectCount(wrapper);

        return count > 0;
    }

    @Override
    public Boolean hasBindMobile(String token) {
        Long userId = JwtUtils.getUserId(token);
        UserInfo userInfo = this.getById(userId);
        return StringUtils.isNotBlank(userInfo.getMobile());
    }

    @Override
    public UserIndexVO getUserIndexVO(String token) {
        Long userId = JwtUtils.getUserId(token);
        UserIndexVO userIndexVO = userInfoMapper.selectUserIndexVoByUserId(userId);
        return userIndexVO;
    }
}
